
#include <cstdio>
#include <BFile>
#include <BStyle>
#include <BPainter>
#include <BReadWrite>
#include <BVBoxLayout>
#include <BHBoxLayout>
#include <BGridLayout>
#include <BDockLayout>
#include <BStackLayout>
#include <BMessageBox>
#include <BCursor>
#include <BSystem>
#include <BColorDialog>

#include <BFog>
#include <BCone>
#include <BCube>
#include <BCapsule>
#include <BCylinder>
#include <BSphere>
#include <BGeoSphere>
#include <BSurface>
#include <BTerrain>
#include <BMaterial>
#include <BBillboard>

#include "ImportDialog.h"
#include "MainWindow.h"

MainWindow::MainWindow()
{
	initMenus();

	_fileDialog = new FileDialog(this);
	_organizeDialog = new OrganizeDialog(this);
	_modifyDialog = new ModifyDialog(this);
	_modifyDialog->setTitle("Modify Objects");
	_modifyDialog->setSize(300);

	BHBoxLayout* buttonLayout = new BHBoxLayout();
	{
		_importButton = new BButton("import");
		_exportButton = new BButton("export");
		_resetButton = new BButton("reset");
		_viewButton = new BButton("view");
		_modifyButton = new BButton("modify");

		buttonLayout->addWidget(_importButton);
		buttonLayout->addWidget(_exportButton);
		buttonLayout->addWidget(_resetButton);
		buttonLayout->addWidget(_viewButton);
		buttonLayout->addWidget(_modifyButton);
		buttonLayout->setSpacing(2);
		buttonLayout->addSpring();
	}

	BMenu* menu = new BMenu();
	{
		_frameCheckBox = new BCheckBox("frame");
		_lightingCheckBox = new BCheckBox("lighting");
		_lightingCheckBox->setChecked(true);
		_showNormalsCheckBox = new BCheckBox("show-normals");
		_normalLengthSlider = new BSlider();

		_gridLinesGroupBox = new BGroupBox("Grid Lines");
		_gridLinesGroupBox->setCheckable(true);
		_gridLinesGroupBox->setAlign(Align_Center);
		{
			BLabel* gridSizeLabel = new BLabel("Grid Size");
			_gridSizeSpinBox = new BRealSpinBox();

			BLabel* gridSectionLabel = new BLabel("Grid Section");
			_gridSegmentSpinBox = new BSpinBox();

			BLabel* gridColorLabel = new BLabel("Grid Color");
			_gridColorButton = new BButton();
			_gridColorButton->setForm(Form_IconOnly);
			_gridColorButton->setGraph(Graph_Circle_Fill);

			BGridLayout* gridLayout = new BGridLayout(_gridLinesGroupBox);
			gridLayout->setWidget(1, 0, gridSizeLabel);
			gridLayout->setWidget(1, 1, _gridSizeSpinBox);
			gridLayout->setWidget(2, 0, gridSectionLabel);
			gridLayout->setWidget(2, 1, _gridSegmentSpinBox);
			gridLayout->setWidget(3, 0, gridColorLabel);
			gridLayout->setWidget(3, 1, _gridColorButton);

			connect(_gridLinesGroupBox, Signal_Checked, &MainWindow::slotGridLineVisibleChecked);
			connect(_gridSizeSpinBox, Signal_EditFinished, &MainWindow::slotGrdiSizeEditFinished);
			connect(_gridSegmentSpinBox, Signal_EditFinished, &MainWindow::slotGridSegmentEditFinished);
			connect(_gridColorButton, Signal_Clicked, &MainWindow::slotGridColorButtonClicked);
		}

		BVBoxLayout* vlayout = new BVBoxLayout(menu);
		vlayout->addWidget(_frameCheckBox);
		vlayout->addWidget(_lightingCheckBox);
		vlayout->addWidget(_showNormalsCheckBox);
		vlayout->addWidget(_normalLengthSlider);
		vlayout->addWidget(_gridLinesGroupBox);
	}
	_viewButton->setMenu(menu);

	_sceneTree = new BTreeWidget();

	_nameEdit = new BLineEdit(_sceneTree);
	_nameEdit->hide();

	_viewer = new BViewer();
	{
		_camera = new BCamera();
		_camera->setColor(0, 0, 0, 128);
		_handler = new MyHandler();
		_scene = new BScene("Scene");

		_viewer->setHandler(_handler);
		_viewer->setCamera(_camera);
		_viewer->setScene(_scene);
		_sceneTree->setAsset(_scene);

		BDockLayout* dockLayout = new BDockLayout(_viewer);
		{
			_cameraPanel = new CameraPanel();
			_cameraPanel->setAsset(_camera);
			//_cameraPanel->setFolded(true);
			dockLayout->addWidget(_cameraPanel, Align_LeftBottom);
			dockLayout->setSplitable(true);
			dockLayout->setSpacing(5);
		}
	}
	_viewerMenu = new BMenu(_viewer);

	_propertyBoard = new PropertyBoard();
	_propertyBoard->setAreaPolicy(Policy_Preferred | Policy_Expanding, Policy_Preferred);
	_propertyBoard->setSizePolicy(Policy_Preferred | Policy_Dynamic);

	BHBoxLayout* splitLayout = new BHBoxLayout();
	splitLayout->setSplitable(true);
	splitLayout->setSpacing(8);
	splitLayout->addWidget(_sceneTree, 20);
	splitLayout->addWidget(_viewer, 100);
	splitLayout->addWidget(_propertyBoard, 10);

	BVBoxLayout* vlayout = new BVBoxLayout(this);
	vlayout->setSpacing(2);
	vlayout->addLayout(buttonLayout, 0);
	vlayout->addLayout(splitLayout, 100);

	initMenus();

	connect("target", &MainWindow::slotTargetSelected);
	connect("delete", &MainWindow::slotDeleteTarget);

	connect(_nameEdit, Signal_Focused, &MainWindow::slotNameEditFocused);
	connect(_importButton, Signal_Clicked, &MainWindow::slotImportButtonClicked);
	connect(_exportButton, Signal_Clicked, &MainWindow::slotExportButtonClicked);
	connect(_resetButton, Signal_Clicked, &MainWindow::slotResetButtonClicked);
	connect(_frameCheckBox, Signal_Checked, &MainWindow::slotFrameChecked);
	connect(_lightingCheckBox, Signal_Checked, &MainWindow::slotLightingChecked);
	connect(_showNormalsCheckBox, Signal_Checked, &MainWindow::slotShowNormalsChecked);
	connect(_normalLengthSlider, Signal_Sliding, &MainWindow::slotNormalLengthEdited);
	connect(_modifyButton, Signal_Clicked, &MainWindow::slotmodifyButtonClicked);
	connect(_sceneTree, Signal_ItemClicked, &MainWindow::slotTreeItemClicked);
	connect(_sceneTree, Signal_RightClicked, &MainWindow::slotTreeRightClicked);
	connect(_viewer, Signal_RightClicked, &MainWindow::slotViewerRightClicked);
	connect(_scene, Signal_SpaceChanged, &MainWindow::slotSceneSpaceChanged);
	connect(_scene, Signal_Insert, &MainWindow::slotSceneInserted);
	connect(_scene, Signal_Remove, &MainWindow::slotSceneRemoved);

	_gridLinesGroupBox->setChecked(_handler->gridLineVisible());
	_gridSizeSpinBox->setValue(_handler->gridSize().width());
	_gridSegmentSpinBox->setValue(_handler->gridSegment());
	_gridColorButton->setColor(_handler->gridColor());

	_target = new Target(_scene);
}
MainWindow::~MainWindow()
{

}

bool MainWindow::openFile(const BString& fileName)
{
	if (fileName.empty())
		return false;
	BObjectHolder object = ReadFile(fileName);
	if (!object)
	{
		BMessageBox::Information(this, "Information", "Open file failed !", Button_Ok, Button_Ok);
		return false;
	}
	if (BScene* scene = object.as<BScene>())
	{
		BGroup* group = new BGroup(scene->name());
		for (int i = 0; i < scene->shapeCount(); i++)
		{
			BShape* shape = scene->shape(i);
			group->insert(shape);
		}
		for (int i = 0; i < scene->nodeCount(); i++)
		{
			BNode* node = scene->node(i);
			group->insert(node);
		}
		for (int i = 0; i < scene->groupCount(); i++)
		{
			BGroup* child = scene->group(i);
			group->addChild(child);
		}
		for (int i = 0; i < scene->constraintCount(); i++)
		{
			BConstraint* constraint = scene->constraint(i);
			group->insert(constraint);
		}
		object = group;
	}
	if (BShape* shape = object.as<BShape>())
	{
		_scene->insert(shape);
		_handler->focus(shape);
		emit("target", new Target(object, _scene));
	}
	if (BNode* node = object.as<BNode>())
	{
		_scene->insert(node);
		_handler->focus(node);
		emit("target", new Target(node, _scene));
	}
	if (BGroup* group = object.as<BGroup>())
	{
		_scene->insert(group);
		_handler->focus(group);
		emit("target", new Target(group, _scene));
	}
	if (BConstraint* constraint = object.as<BConstraint>())
	{
		_scene->insert(constraint);
		emit("target", new Target(constraint, _scene));
	}

	BSpace space;
	space.expand(_scene->space());
	_handler->setGridSize(space.size() * 2);

	return true;
}

void MainWindow::initMenus()
{
	_itemMenu = new BMenu();

	BMenu* createMenu = _itemMenu->addMenu("Create");
	BAction* createGroupAction = createMenu->addAction("Group");
	connect(createGroupAction, Signal_Triggered, &MainWindow::slotCreateGroupActionTriggered);

	if (BMenu* createNodeMenu = createMenu->addMenu("Node"))
	{
		createNodeMenu->addAction("Node");
		createNodeMenu->addAction("Light");
		createNodeMenu->addAction("Camera");
		createNodeMenu->addAction("Fog");
		connect(createNodeMenu, Signal_Triggered, &MainWindow::slotCreateNodeActionTriggered);
	}
	if (BMenu* createShapeMenu = createMenu->addMenu("Shape"))
	{
		createShapeMenu->addAction("Cone");
		createShapeMenu->addAction("Cube");
		createShapeMenu->addAction("Capsule");
		createShapeMenu->addAction("Cylinder");
		createShapeMenu->addAction("Sphere");
		createShapeMenu->addAction("GeoSphere");
		createShapeMenu->addAction("Surface");
		createShapeMenu->addAction("Terrain");
		createShapeMenu->addAction("Billboard");
		connect(createShapeMenu, Signal_Triggered, &MainWindow::slotCreateShapeActionTriggered);
	}

	BMenu* organizeMenu = _itemMenu->addMenu("Organize");
	organizeMenu->addAction("Group");
	organizeMenu->addAction("Node");

	BAction* copyAction = _itemMenu->addAction("Copy");
	BAction* cutAction = _itemMenu->addAction("Cut");
	BAction* pasteAction = _itemMenu->addAction("Paste");
	BAction* renameAction = _itemMenu->addAction("Rename");
	BAction* removeAction = _itemMenu->addAction("Remove");

	connect(organizeMenu, Signal_Triggered, &MainWindow::slotOrganizeMenuTriggered);
	connect(copyAction, Signal_Triggered, &MainWindow::slotCopyActionTriggered);
	connect(cutAction, Signal_Triggered, &MainWindow::slotCutActionTriggered);
	connect(pasteAction, Signal_Triggered, &MainWindow::slotPasteActionTriggered);
	connect(renameAction, Signal_Triggered, &MainWindow::slotRenameActionTriggered);
	connect(removeAction, Signal_Triggered, &MainWindow::slotRemoveActionTriggered);
}
const char* MainWindow::primName(Primitive prim)
{
	switch (prim)
	{
	case Primitive_Points:
		return "Points";
	case Primitive_Lines:
		return "Lines";
	case Primitive_LineStrip:
		return "LineStrip";
	case Primitive_LineLoop:
		return "LineLoop";
	case Primitive_Triangles:
		return "Triangles";
	case Primitive_TriangleStrip:
		return "TriangleStrip";
	case Primitive_TriangleFan:
		return "TriangleFan";
	case Primitive_Quads:
		return "Quads";
	case Primitive_QuadStrip:
		return "QuadStrip";
	case Primitive_Polygon:
		return "Polygon";
	default:
		return "None";
	}
}
BString MainWindow::findValidName(const BScene* scene, const BString& name)
{
	BString realName;
	int number = 0;
	while (number < 9999)
	{
		realName.reset();
		realName << name << number++;
		if (scene->shape(name))
			continue;
		if (scene->node(name))
			continue;
		if (scene->group(name))
			continue;
		if (scene->constraint(name))
			continue;
		break;
	}
	return realName;
}
BString MainWindow::findValidName(const BGroup* group, const BString& name)
{
	BString realName;
	int number = 0;
	while (number < 9999)
	{
		realName.reset();
		realName << name << number++;
		if (group->shape(name))
			continue;
		if (group->node(name))
			continue;
		if (group->child(name))
			continue;
		if (group->constraint(name))
			continue;
		break;
	}
	return realName;
}
BString MainWindow::findValidName(const BNode* node, const BString& name)
{
	BString realName;
	int number = 0;
	while (number < 9999)
	{
		realName.reset();
		realName << name << number++;
		if (node->shape(name))
			continue;
		break;
	}
	return realName;
}
BIcon* MainWindow::typedIcon(const BObject* object)
{
	const BStyle* style = this->realStyle();
	for (int i = object->typeCount(); i >= 0; i--)
	{
		const BString& type = object->typeName(i);
		if (BIcon* icon = style->icon(type))
			return icon;
	}
	return 0;
}
BObject* MainWindow::copyObject(const BObject* object)
{
	if (const BShape* shape = dynamic_cast<const BShape*>(object))
	{
		return shape->clone();
	}
	if (const BNode* node = dynamic_cast<const BNode*>(object))
	{
		return node->clone();
	}
	if (const BGroup* group = dynamic_cast<const BGroup*>(object))
	{
		return group->clone();
	}
	return 0;
}
void MainWindow::freshMenuIcons(BMenu* menu)
{
	const BStyle* style = this->realStyle();
	BString text = menu->title();
	text.lower();
	BIcon* icon = style->icon(text);
	menu->setTitleIcon(icon);
	for (int i = 0; i < menu->count(); i++)
	{
		if (BMenu* child = menu->menu(i))
		{
			freshMenuIcons(child);
			continue;
		}
		if (BAction* action = menu->action(i))
		{
			text.reset();
			text << action->text();
			text.lower();
			BIcon* icon = style->icon(text);
			action->setIcon(icon);
			continue;
		}
	}
}
BTreeItem* MainWindow::createTreeItem(BScene* scene)
{
	BTreeItem* item = new BTreeItem(scene->name());
	item->setAsset(scene);
	item->setIcon(typedIcon(scene));
	connect(scene, Signal_Renamed, &MainWindow::slotNodeRenamed);
	for (int i = 0; i < scene->shapeCount(); i++)
	{
		BTreeItem* shapeItem = createTreeItem(scene->shape(i));
		item->addChild(shapeItem);
	}
	for (int i = 0; i < scene->nodeCount(); i++)
	{
		BTreeItem* nodeItem = createTreeItem(scene->node(i));
		item->addChild(nodeItem);
	}
	for (int i = 0; i < scene->groupCount(); i++)
	{
		BTreeItem* groupItem = createTreeItem(scene->group(i));
		item->addChild(groupItem);
	}
	for (int i = 0; i < scene->constraintCount(); i++)
	{
		BTreeItem* constraintItem = createTreeItem(scene->constraint(i));
		item->addChild(constraintItem);
	}
	return item;
}
BTreeItem* MainWindow::createTreeItem(BGroup* group)
{
	BTreeItem* item = new BTreeItem(group->name());
	item->setAsset(group);
	item->setIcon(typedIcon(group));
	connect(group, Signal_Renamed, &MainWindow::slotNodeRenamed);
	for (int i = 0; i < group->shapeCount(); i++)
	{
		BTreeItem* shapeItem = createTreeItem(group->shape(i));
		item->addChild(shapeItem);
	}
	for (int i = 0; i < group->nodeCount(); i++)
	{
		BTreeItem* nodeItem = createTreeItem(group->node(i));
		item->addChild(nodeItem);
	}
	for (int i = 0; i < group->childCount(); i++)
	{
		BTreeItem* childItem = createTreeItem(group->child(i));
		item->addChild(childItem);
	}
	for (int i = 0; i < group->constraintCount(); i++)
	{
		BTreeItem* constraintItem = createTreeItem(group->constraint(i));
		item->addChild(constraintItem);
	}
	return item;
}
BTreeItem* MainWindow::createTreeItem(BNode* node)
{
	BTreeItem* item = new BTreeItem(node->name());
	item->setAsset(node);
	item->setIcon(typedIcon(node));
	connect(node, Signal_Renamed, &MainWindow::slotNodeRenamed);
	for (int i = 0; i < node->shapeCount(); i++)
	{
		BShape* shape = node->shape(i);
		BTreeItem* shapeItem = createTreeItem(shape);
		item->addChild(shapeItem);
	}
	return item;
}
BTreeItem* MainWindow::createTreeItem(BShape* shape)
{
	BTreeItem* item = new BTreeItem(shape->name());
	item->setAsset(shape);
	item->setExpanded(false);
	item->setIcon(typedIcon(shape));
	connect(shape, Signal_Renamed, &MainWindow::slotNodeRenamed);
	if (BGeometry* geometry = dynamic_cast<BGeometry*>(shape))
	{
		for (int ei = 0; ei < geometry->elementCount(); ei++)
		{
			BElement* element = geometry->element(ei);
			BTreeItem* elementItem = item->addChild(primName(element->primitive()));
			elementItem->setAsset(element);
			elementItem->setIcon(typedIcon(element));
		}
	}
	return item;
}
BTreeItem* MainWindow::createTreeItem(BConstraint* constraint)
{
	BTreeItem* item = new BTreeItem(constraint->name());
	item->setAsset(constraint);
	item->setExpanded(false);
	item->setIcon(typedIcon(constraint));
	connect(constraint, Signal_Renamed, &MainWindow::slotNodeRenamed);
	return item;
}
void MainWindow::removeTreeItem(BTreeItem* item)
{
	if (BTreeItem* parentItem = item->parent())
	{
		if (BNode* node = parentItem->asset())
		{
			if (BShape* shape = item->asset())
				node->removeShape(shape);
		}
		else if (BGroup* group = parentItem->asset())
		{
			if (BShape* shape = item->asset())
				group->remove(shape);
			else if (BNode* node = item->asset())
				group->remove(node);
			else if (BConstraint* constraint = item->asset())
				group->remove(constraint);
			else if (BGroup* child = item->asset())
				group->removeChild(child);
		}
		else if (BScene* scene = parentItem->asset())
		{
			if (BShape* shape = item->asset())
				scene->remove(shape);
			else if (BNode* node = item->asset())
				scene->remove(node);
			else if (BGroup* group = item->asset())
				scene->remove(group);
			else if (BConstraint* constraint = item->asset())
				scene->remove(constraint);
		}
		parentItem->removeChild(item);
	}
	else
	{
		_sceneTree->removeItem(item);
	}
}

void MainWindow::slotImportButtonClicked()
{
	_fileDialog->setTitle("Import File");
	_fileDialog->setNameFilter("*(All Files); *.3ds; *.obj; *.obc; *.osc; *.stl");
	if (_fileDialog->execute())
	{
		const BStringList& fileNames = _fileDialog->entryNameList();
		if (fileNames.size() == 1 && BFile::Exist(fileNames.first()))
		{
			openFile(fileNames.first());
		}
		else
		{
			ImportDialog* importDialog = new ImportDialog(this);
			importDialog->setAsset(_target);
			importDialog->setFileNames(fileNames);
			importDialog->execute();
		}
	}
}
void MainWindow::slotExportButtonClicked()
{
	BObject* object = _scene;
	if (_sceneTree->selectedItemCount() > 1)
	{
		BGroup* group = new BGroup();
		for (int i = 0; i < _sceneTree->selectedItemCount(); i++)
		{
			BTreeItem* item = _sceneTree->selectedItem(i);
			if (BShape* shape = item->asset())
				group->insert(shape);
			else if (BNode* node = item->asset())
				group->insert(node);
			else if (BConstraint* constraint = item->asset())
				group->insert(constraint);
			else if (BGroup* child = item->asset())
				group->addChild(child);
		}
		object = group;
	}
	else if (_sceneTree->selectedItemCount() == 1)
	{
		BTreeItem* item = _sceneTree->selectedItem();
		object = item->asset();
	}
	if (object == 0)
		return;
	BString formatStr("*.obc,*.otc,*.osc,*.obj,*.3ds,*.stl");
	const BString& fileName = BFileDialog::OpenFile("Choose Export File", "", formatStr);
	if (fileName.size())
	{
		if (WriteFile(fileName, object))
		{
			BMessageBox::Information(this, "", "Export file successful !");
		}
		else
		{
			BMessageBox::Information(this, "", "Export file failed !");
		}
	}
}
void MainWindow::slotResetButtonClicked()
{
	_scene->clear();
	_sceneTree->clearItems();
	emit("target", new Target(_scene));
}
void MainWindow::slotmodifyButtonClicked()
{
	_modifyDialog->setSceneTree(_sceneTree);
	_modifyDialog->execute();
}

void MainWindow::slotCreateGroupActionTriggered(BObject* object, const BValue& value)
{
	BAction* action = value;
	if (action->text() == "Group")
	{
		BGroup* group = new BGroup();
		for (int i = 0; i < _sceneTree->selectedItemCount(); i++)
		{
			BTreeItem* item = _sceneTree->selectedItem(i);
			if (BNode* node = item->asset())
			{
				group->insert(node);
				continue;
			}
			if (BGroup* child = item->asset())
			{
				group->addChild(child);
				continue;
			}
		}
		if (BGroup* parent = _target->group())
		{
			group->setName(findValidName(parent, "Group"));
			parent->addChild(group);
		}
		else
		{
			group->setName(findValidName(_scene, "Group"));
			_scene->insert(group);
		}
		emit("target", new Target(group, _scene));
		return;
	}
}
void MainWindow::slotCreateNodeActionTriggered(BObject* object, const BValue& value)
{
	BAction* action = value;
	if (action->text() == "Node")
	{
		BNode* node = new BNode();
		for (int i = 0; i < _sceneTree->selectedItemCount(); i++)
		{
			BTreeItem* item = _sceneTree->selectedItem(i);
			if (BShape* shape = item->asset())
			{
				node->addShape(shape);
			}
		}
		Target* target = 0;
		BString name;
		BTreeItem* parentItem = _sceneTree->selectedItem()->parent();
		while (parentItem)
		{
			if (BScene* parentScene = parentItem->asset())
			{
				parentScene->insert(node);
				name = findValidName(parentScene, action->text());
				target = new Target(node, parentScene);
				break;
			}
			if (BGroup* parentGroup = parentItem->asset())
			{
				parentGroup->insert(node);
				name = findValidName(parentGroup, action->text());
				target = new Target(node, _scene);
				break;
			}
			parentItem = parentItem->parent();
		}
		node->setName(name);
		BTreeItem* nodeItem = createTreeItem(node);
		parentItem->addChild(nodeItem);
		while (BTreeItem* item = _sceneTree->selectedItem())
		{
			_sceneTree->removeItem(item);
		}
		_sceneTree->scrollToItem(nodeItem);
		emit("target", target);
		return;
	}
	if (action->text() == "Light")
	{

	}
	if (action->text() == "Camera")
	{

	}
	if (action->text() == "Fog")
	{
		BFog* fog = new BFog();
	}
}
void MainWindow::slotCreateShapeActionTriggered(BObject* object, const BValue& value)
{
	BAction* action = value;
	BShape* shape = 0;
	if (action->text() == "Cone")
	{
		shape = new BCone();
	}
	if (action->text() == "Cube")
	{
		shape = new BCube();
	}
	if (action->text() == "Capsule")
	{
		shape = new BCapsule();
	}
	if (action->text() == "Cylinder")
	{
		shape = new BCylinder();
	}
	if (action->text() == "Sphere")
	{
		shape = new BSphere();
	}
	if (action->text() == "GeoSphere")
	{
		shape = new BGeoSphere();
	}
	if (action->text() == "Surface")
	{
		shape = new BSurface();
	}
	if (action->text() == "Terrain")
	{
		shape = new BTerrain();
	}
	if (action->text() == "Billboard")
	{
		shape = new BBillboard();
	}
	if (shape)
	{
		shape->setName(action->text());
		_scene->insert(shape);
		BTreeItem* shapeItem = _sceneTree->addTopItem(shape->name());
		shapeItem->setAsset(shape);
		shapeItem->setIcon(typedIcon(shape));
		shapeItem->setExpanded(false);
		if (BGeometry* geometry = dynamic_cast<BGeometry*>(shape))
		{
			for (int ei = 0; ei < geometry->elementCount(); ei++)
			{
				BElement* element = geometry->element(ei);
				BTreeItem* elementItem = shapeItem->addChild(primName(element->primitive()));
				elementItem->setAsset(element);
				elementItem->setIcon(typedIcon(element));
			}
		}
		_handler->focus(shape);
		return;
	}
}
void MainWindow::slotOrganizeMenuTriggered(BObject* object, const BValue& value)
{
	BAction* action = value;
	if (_target.empty())
		emit("target", new Target(_scene));
	if (action->text() == "Group")
	{
		BGroup* group = new BGroup();
		_organizeDialog->setTarget(_target);
		_organizeDialog->setAsset(group);
		_organizeDialog->execute();
		return;
	}
	if (action->text() == "Node")
	{
		BNode* node = new BNode();
		_organizeDialog->setTarget(_target);
		_organizeDialog->setAsset(node);
		_organizeDialog->execute();
		return;
	}
}
void MainWindow::slotCopyActionTriggered(BObject* object, const BValue& value)
{
	BObjectHolderArray objects;
	for (int i = 0; i < _sceneTree->selectedItemCount(); i++)
	{
		BTreeItem* item = _sceneTree->selectedItem();
		if (BObject* object = item->asset())
		{
			BObject* newObj = copyObject(object);
			objects.append(newObj);
		}
	}
	BSystem::SetClipBoard(objects);
}
void MainWindow::slotCutActionTriggered(BObject* object, const BValue& value)
{
	if (_target->shapeCount() > 0)
	{
		if (BNode* node = _target->node())
		{
			for (int i = 0; i < _target->shapeCount(); i++)
				node->removeShape(_target->shape(i));
		}
		else if (BGroup* group = _target->group())
		{
			for (int i = 0; i < _target->shapeCount(); i++)
				group->remove(_target->shape(i));
		}
		else
		{
			for (int i = 0; i < _target->shapeCount(); i++)
				_scene->remove(_target->shape(i));
		}
		BSystem::SetClipBoard(_target->shapes());
		_target->clearShapes();
		emit("target", _target);
		return;
	}
	if (_target->nodeCount() > 0)
	{
		if (BGroup* group = _target->group())
		{
			for (int i = 0; i < _target->nodeCount(); i++)
				group->remove(_target->node(i));
		}
		else
		{
			for (int i = 0; i < _target->nodeCount(); i++)
				_scene->remove(_target->node(i));
		}
		BSystem::SetClipBoard(_target->nodes());
		_target->clearNodes();
		emit("target", _target);
		return;
	}
	if (_target->groupCount() > 0)
	{
		for (int i = 0; i < _target->groupCount(); i++)
		{
			BGroup* group = _target->group(i);
			if (BGroup* parent = group->parent())
				parent->removeChild(group);
			else
				_scene->remove(group);
		}
		BSystem::SetClipBoard(_target->groups());
		_target->clearGroups();
		emit("target", _target);
		return;
	}
}
void MainWindow::slotPasteActionTriggered(BObject* object, const BValue& value)
{
	const BValue& clipedValue = BSystem::GetClipBoard();
	if (clipedValue.is<BShapeHolderArray>())
	{
		BShapeHolderArray& shapes = clipedValue;
		if (BNode* node = _target->node())
		{
			for (int i = 0; i < shapes.size(); i++)
				node->addShape(shapes[i]);
		}
		else if (BGroup* group = _target->group())
		{
			for (int i = 0; i < shapes.size(); i++)
				group->insert(shapes[i]);
		}
		else
		{
			for (int i = 0; i < shapes.size(); i++)
				_scene->insert(shapes[i]);
		}
	}
	else if (clipedValue.is<BNodeHolderArray>())
	{
		BNodeHolderArray& nodes = clipedValue;
		if (BGroup* group = _target->group())
		{
			for (int i = 0; i < nodes.size(); i++)
				group->insert(nodes[i]);
		}
		else
		{
			for (int i = 0; i < nodes.size(); i++)
				_scene->insert(nodes[i]);
		}
	}
	BSystem::CleanClipBoard();
}
void MainWindow::slotRenameActionTriggered(BObject* object, const BValue& value)
{
	if (BTreeItem* item = _sceneTree->selectedItem())
	{
		BRect textArea = item->textArea();
		_nameEdit->setAsset(item);
		_nameEdit->setText(item->text());
		_nameEdit->setRect(textArea);
		_nameEdit->setMinSize(48, 0);
		_nameEdit->setMaxSize(_sceneTree->centerRect().right() - textArea.left(), 9999999);
		_nameEdit->setFocused(true);
		_nameEdit->popup();
	}
}
void MainWindow::slotRemoveActionTriggered(BObject* object, const BValue& value)
{
	if (_target->shapeCount() > 0)
	{
		if (BNode* node = _target->node())
		{
			for (int i = 0; i < _target->shapeCount(); i++)
				node->removeShape(_target->shape(i));
		}
		else if (BGroup* group = _target->group())
		{
			for (int i = 0; i < _target->shapeCount(); i++)
				group->remove(_target->shape(i));
		}
		else
		{
			for (int i = 0; i < _target->shapeCount(); i++)
				_scene->remove(_target->shape(i));
		}
		_target->clearShapes();
		emit("target", _target);
		return;
	}
	if (_target->nodeCount() > 0)
	{
		if (BGroup* group = _target->group())
		{
			for (int i = 0; i < _target->nodeCount(); i++)
				group->remove(_target->node(i));
		}
		else
		{
			for (int i = 0; i < _target->nodeCount(); i++)
				_scene->remove(_target->node(i));
		}
		_target->clearNodes();
		emit("target", _target);
		return;
	}
	if (_target->groupCount() > 0)
	{
		for (int i = 0; i < _target->groupCount(); i++)
		{
			BGroup* group = _target->group(i);
			if (BGroup* parent = group->parent())
				parent->removeChild(group);
			else
				_scene->remove(group);
		}
		_target->clearGroups();
		emit("target", _target);
		return;
	}
}

void MainWindow::slotNameEditFocused(BObject* object, const BValue& value)
{
	if (value == false)
	{
		_nameEdit->hide();
		const BString& name = _nameEdit->text();
		BTreeItem* item = _nameEdit->asset();
		item->setText(name);
		BObject* object = item->asset();
		object->setName(name);
		_nameEdit->setAsset(BValue());
	}
}
void MainWindow::slotFrameChecked()
{
	PolyMode pmode = Poly_Fill;
	if (_frameCheckBox->checked())
		pmode = Poly_Line;
	for (int i = 0; i < _scene->nodeCount(); i++)
	{
		BNode* node = _scene->node(i);
		for (int si = 0; si < node->shapeCount(); si++)
		{
			BShape* shape = node->shape(si);
			shape->setPolyMode(pmode);
		}
	}
	for (int i = 0; i < _scene->shapeCount(); i++)
	{
		BShape* shape = _scene->shape(i);
		shape->setPolyMode(pmode);
	}
	_viewer->fresh();
}
void MainWindow::slotLightingChecked()
{
	bool lighting = _lightingCheckBox->checked();
	for (int i = 0; i < _scene->nodeCount(); i++)
	{
		BNode* node = _scene->node(i);
		for (int si = 0; si < node->shapeCount(); si++)
		{
			BShape* shape = node->shape(si);
			shape->setLighting(lighting);
		}
	}
	for (int i = 0; i < _scene->shapeCount(); i++)
	{
		BShape* shape = _scene->shape(i);
		shape->setLighting(lighting);
	}
	_camera->fresh();
}
void MainWindow::slotShowNormalsChecked()
{
	bool checked = _showNormalsCheckBox->checked();
	_handler->setShowNormals(checked);
}
void MainWindow::slotNormalLengthEdited()
{
	double ratio = _normalLengthSlider->ratio();
	_handler->setNormalLengthRatio((float)ratio);
}
void MainWindow::slotGridLineVisibleChecked(BObject* object, const BValue& value)
{
	BGroupBox* groupBox = (BGroupBox*)object;
	bool visible = value;
	for (int i = 0; i < groupBox->childCount(); i++)
	{
		groupBox->child(i)->setEnabled(visible);
	}
	_handler->setGridLineVisible(visible);
}
void MainWindow::slotGrdiSizeEditFinished(BObject* object, const BValue& value)
{
	BReal gridSize = value;
	_handler->setGridSize(gridSize);
}
void MainWindow::slotGridSegmentEditFinished(BObject* object, const BValue& value)
{
	int segment = value;
	_handler->setGridSegment(segment);
}
void MainWindow::slotGridColorButtonClicked()
{
	BColor color = _gridColorButton->color();
	color = BColorDialog::ChooseColor("Choose GridLine Color", color);
	_gridColorButton->setColor(color);
	_handler->setGridColor(color);
}
void MainWindow::slotTreeItemClicked(BObject* object, const BValue& value)
{
	if (_nameEdit->asset() != value)
	{
		_nameEdit->setAsset(value);
		_nameEdit->setPos(BCursor::GetPos());
	}
	else
	{
		BTreeItem* item = value;
		bool editing = (_nameEdit->pos() - BCursor::GetPos()).length2() > 6;
		if (item && editing)
		{
			BRect area = item->textArea();
			BSize ssize = _nameEdit->shellSize();
			BRect rect = area + ssize;
			rect -= BPoint(ssize.width() / 2, ssize.height() / 2);
			if (rect.right() >= _sceneTree->centerRect().right())
				rect.right() = _sceneTree->centerRect().right() - 1;
			_nameEdit->setParent(_sceneTree);
			_nameEdit->setRect(rect);
			_nameEdit->setText(item->text());
			_nameEdit->popup();
		}
	}
	Target* target = new Target(_scene);
	for(int i = 0;i < _sceneTree->selectedItemCount(); i++)
	{
		BTreeItem* item = _sceneTree->selectedItem(i);
		if (BShape* shape = item->asset())
		{
			target->insertShape(shape);
			if (BTreeItem* parentItem = item->parent())
			{
				if (BNode* node = parentItem->asset())
					target->insertNode(node);
				else if (BGroup* group = parentItem->asset())
					target->insertGroup(group);
			}
		}
		else if (BNode* node = item->asset())
		{
			target->insertNode(node);
			target->insertGroup(node->group());
		}
		else if (BGroup* group = item->asset())
		{
			target->insertGroup(group);
		}
	}
	emit("target", target);
}
void MainWindow::slotTreeRightClicked(BObject* object, const BValue& value)
{
	BPoint pos = value;
	_itemMenu->setParent(_sceneTree);
	_itemMenu->setPos(pos);
	_itemMenu->popup();
}
void MainWindow::slotViewerRightClicked(BObject* object, const BValue& value)
{
	const BPoint& pos = value;
}

void MainWindow::slotTargetSelected(BObject* object, const BValue& value)
{
	_target = (Target*)value;
	BTreeItemList selectedItems;
	if (_target && !_target->empty())
	{
		for (int i = 0; i < _target->shapeCount(); i++)
		{
			BShape* shape = _target->shape(i);
			if (BTreeItem* item = _sceneTree->itemOfAsset(shape))
				selectedItems.append(item);
		}
		if (selectedItems.empty())
		{
			for (int i = 0; i < _target->nodeCount(); i++)
			{
				BNode* node = _target->node(i);
				if (BTreeItem* item = _sceneTree->itemOfAsset(node))
					selectedItems.append(item);
			}
		}
		if (selectedItems.empty())
		{
			for (int i = 0; i < _target->constraintCount(); i++)
			{
				BConstraint* constraint = _target->constraint(i);
				if (BTreeItem* item = _sceneTree->itemOfAsset(constraint))
					selectedItems.append(item);
			}
		}
		if (selectedItems.empty())
		{
			for (int i = 0; i < _target->groupCount(); i++)
			{
				BGroup* group = _target->group(i);
				if (BTreeItem* item = _sceneTree->itemOfAsset(group))
					selectedItems.append(item);
			}
		}
	}
	_sceneTree->setSelection(selectedItems);
	if (!_sceneTree->itemVisual(selectedItems.last()))
	{
		_sceneTree->scrollToItem(selectedItems.last());
	}
	if (BTreeItem* treeItem = _sceneTree->selectedItem())
	{
		_propertyBoard->setAsset(treeItem->asset());
	}
	else
	{
		_propertyBoard->setAsset(BValue());
	}
}
void MainWindow::slotDeleteTarget(BObject* object, const BValue& value)
{
	if (BAction* removeAction = _itemMenu->action("Remove"))
	{
		removeAction->trigger();
	}
}
void MainWindow::slotSceneSpaceChanged(BObject* object, const BValue& value)
{
	const BSpace& space = value;
	BReal gridSize = (space.max() - space.min()).length() * 2;
	_handler->setGridSize(gridSize);
	this->fresh();
}
void MainWindow::slotSceneInserted(BObject* object, const BValue& value)
{
	if (BShape* shape = value)
	{
		BTreeItem* item = createTreeItem(shape);
		if (BNode* node = _target->node())
		{
			BTreeItem* parentItem = _sceneTree->itemOfAsset(node);
			parentItem->addChild(item);
		}
		else if (BGroup* group = shape->group())
		{
			BTreeItem* parentItem = _sceneTree->itemOfAsset(group);
			parentItem->addChild(item);
		}
		else if (_scene->contain(shape))
		{
			_sceneTree->addTopItem(item);
		}
		return;
	}
	if (BNode* node = value)
	{
		BTreeItem* item = createTreeItem(node);
		if (BGroup* group = node->group())
		{
			BTreeItem* parentItem = _sceneTree->itemOfAsset(group);
			parentItem->addChild(item);
		}
		else
		{
			_sceneTree->addTopItem(item);
		}
		return;
	}
	if (BConstraint* constraint = value)
	{
		BTreeItem* item = createTreeItem(constraint);
		if (BGroup* parent = constraint->group())
		{
			BTreeItem* parentItem = _sceneTree->itemOfAsset(parent);
			parentItem->addChild(item);
		}
		else
		{
			_sceneTree->addTopItem(item);
		}
		return;
	}
	if (BGroup* group = value)
	{
		BTreeItem* item = createTreeItem(group);
		if (BGroup* parent = group->parent())
		{
			BTreeItem* parentItem = _sceneTree->itemOfAsset(parent);
			parentItem->addChild(item);
		}
		else
		{
			_sceneTree->addTopItem(item);
		}
		return;
	}
}
void MainWindow::slotSceneRemoved(BObject* object, const BValue& value)
{
	if (BTreeItem* item = _sceneTree->itemOfAsset(value))
	{
		_sceneTree->removeItem(item);
	}
}
void MainWindow::slotNodeRenamed(BObject* object, const BValue& value)
{
	const BString& name = value;
	if (BTreeItem* item = _sceneTree->itemOfAsset(object))
	{
		item->setText(name);
	}
}

void MainWindow::adjustEvent(const BEvent& event)
{
	BMainWindow::adjustEvent(event);
}

void MainWindow::styleEvent(const BEvent& event)
{
	BMainWindow::styleEvent(event);
	if (const BStyle* style = event.value())
	{
		_importButton->setIcon(style->icon("import"));
		_exportButton->setIcon(style->icon("export"));
		_resetButton->setIcon(style->icon("reset"));
		freshMenuIcons(_itemMenu);
	}
}
